﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.Text;
using System.Threading;
using System.Web;

namespace SecureService
{
    // HINWEIS: Mit dem Befehl "Umbenennen" im Menü "Umgestalten" können Sie den Klassennamen "Service1" sowohl im Code als auch in der SVC- und der Konfigurationsdatei ändern.
    // HINWEIS: Wählen Sie zum Starten des WCF-Testclients zum Testen dieses Diensts Service1.svc oder Service1.svc.cs im Projektmappen-Explorer aus, und starten Sie das Debuggen.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class BroadcastorService : IBroadcastorService
    {
        private static Dictionary<string, IBroadcastorCallBack> activeClients =
                new Dictionary<string, IBroadcastorCallBack>();

        private static Dictionary<string, ClientInfo> infoClients =
        new Dictionary<string, ClientInfo>();

        private static object lockerNS = new object();

        private void CheckClients()
        {
            try
            {
                foreach (var activeClient in activeClients)
                {
                    if (((IChannel)activeClient.Value).State != CommunicationState.Opened)
                    {
                        activeClients.Remove(activeClient.Key);
                        infoClients.Remove(activeClient.Key);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        public void RegisterClient(string clientID, ClientInfo clientInfo)
        {
            try
            {
                if (clientID != null && clientID != "")
                {
                    try
                    {
                        IBroadcastorCallBack callback =
                        OperationContext.Current.GetCallbackChannel<IBroadcastorCallBack>();
                        //remove the old client
                        if (activeClients.Keys.Contains(clientID)) activeClients.Remove(clientID);
                        activeClients.Add(clientID, callback);

                        if (infoClients.Keys.Contains(clientID)) infoClients.Remove(clientID);
                        infoClients.Add(clientID, clientInfo);
                    }
                    catch (Exception ex)
                    {
                    }
                }

                CheckClients();

                try
                {
                    foreach (var client in infoClients)
                    {
                        if (client.Key != clientID && client.Value.ClientType == ClientInfo.ClientTypes.ManagementConsole)
                        {
                            EventDataType eventData = new EventDataType();
                            eventData.EventType = "NewRegisterClient";
                            string EventMessage = string.Empty;
                            EventMessage += clientID + ";";
                            EventMessage += infoClients[clientID].ClientIP + ";";
                            EventMessage += infoClients[clientID].ClientOS + ";";
                            EventMessage += infoClients[clientID].ClientVersion + ";";
                            eventData.EventMessage = EventMessage;
                            IBroadcastorCallBack callback = activeClients[client.Key];
                            Thread myNewThread = new Thread(() => BroadCastToClient(client.Key, callback, eventData));
                            myNewThread.Start();
                        }
                    }
                }
                catch (Exception ex)
                {
                }
            }
            catch (Exception)
            {

                throw;
            }
        }

        public void NotifyServer(EventDataType eventData)
        {
            try
            {
                Thread myNewThread;

                switch (eventData.EventType)
                {
                    case "ActiveClients":

                        CheckClients();

                        foreach (var client in activeClients)
                        {
                            if (client.Key == eventData.SourceClient)
                            {
                                EventDataType newEventData = new EventDataType();
                                string EventMessage = string.Empty;

                                EventMessage = "LoggedIn";

                                foreach (var activeClient in activeClients)
                                {
                                    EventMessage += "|";
                                    EventMessage += activeClient.Key + ";";
                                    EventMessage += infoClients[activeClient.Key].ClientIP + ";";
                                    EventMessage += infoClients[activeClient.Key].ClientOS + ";";
                                    EventMessage += infoClients[activeClient.Key].ClientVersion + ";";                                        
                                }

                                newEventData.EventMessage = EventMessage;

                                myNewThread = new Thread(() => BroadCastToClient(client.Key, client.Value, newEventData));
                                myNewThread.Start();
                            }
                        }
                        break;
                    default:
                        foreach (var client in activeClients)
                        {
                            if ((client.Key == eventData.TargetClient || eventData.TargetClient == (new Guid()).ToString()) && client.Key != eventData.SourceClient)
                            {
                                myNewThread = new Thread(() => BroadCastToClient(client.Key, client.Value, eventData));
                                myNewThread.Start();                    
                            }
                        }
                        break;
                }


            }
            catch (Exception)
            {
            }
        }

        private void BroadCastToClient(string key, IBroadcastorCallBack client ,EventDataType eventData)
        {
            try
            {
                client.BroadcastToClient(eventData);
            }
            catch (Exception ex)
            {
                activeClients.Remove(key);
                if (eventData.SourceClient != null && eventData.SourceClient != "")
                {
                    IBroadcastorCallBack _client = activeClients[eventData.SourceClient];
                    {
                        EventDataType eventDataReset = new EventDataType();
                        eventDataReset.EventType = "Reset";
                        _client.BroadcastToClient(eventDataReset);
                    }
                }
            }
        }

    }


}
